package cn.tedu.javacv.service;

import cn.tedu.common.ex.ServiceException;
import cn.tedu.javacv.util.DirectionConstant;
import cn.tedu.javacv.util.ErrorConstant;
import cn.tedu.javacv.util.ImageStitchingUtils;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.opencv_core.Mat;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


@Service
@Slf4j
public class ImgStitchingServiceImpl implements ImgStitchingService{


    @Override
    public void handle(MultipartFile multipartFile, Double intervalTime, String direction) {
        List<Mat> images = null;
        try {
            File tempFile = ImageStitchingUtils.transform(multipartFile);
            images = ImageStitchingUtils.videoToImages(tempFile, intervalTime);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        // 根据视频方向调整
        if (direction.equals(DirectionConstant.RIGHT_TO_LEFT)) {
            Collections.reverse(images);
            System.out.println(images.toString());
        }
        // 将图像分开处理(每组最大40个)
        List<List<Mat>> lists = splitList(images);
        for (List<Mat> list : lists) {
            List<Mat> matList = concatenateImages(list);
            for (Mat mat : matList) {
                ImageStitchingUtils.imageSplit(mat);
            }
            System.out.println(matList.toString());
        }

    }


    private List<Mat> concatenateImages(List<Mat> images) {
        List<Mat> result = new ArrayList<>();
        while (images.size() > 1) {
            List<Mat> concatenatedFiles = new ArrayList<>();

            // 从第一个元素开始每两个进行拼接
            for (int i = 0; i < images.size() - 1; i += 2) {
                Mat mat1 = images.get(i);
                Mat mat2 = images.get(i + 1);

                // 拼接两个文件并将结果添加到新的列表中
                Mat resultFile;
                try {
                    resultFile = ImageStitchingUtils.concatenateTwoImages(mat1, mat2);
                    concatenatedFiles.add(resultFile);
                } catch (ServiceException e) {
                    log.error(e.getMessage());
                    if (e.getMessage().equals(ErrorConstant.ERR_CAMERA_PARAMS_ADJUST_FAIL) || e.getMessage().equals(ErrorConstant.ERR_NEED_MORE_IMGS)) {
                        if (i > 1) {
                            Mat tempMat = images.get(i-1);
                            Mat tempFile1;
                            Mat tempFile2;
                            try {
                                tempFile1 = ImageStitchingUtils.concatenateTwoImages(tempMat, mat1);
                                concatenatedFiles.add(tempFile1);
                            } catch (Exception exception) {
                                log.error(exception.getMessage());
                            }
                            try {
                                tempFile2 = ImageStitchingUtils.concatenateTwoImages(tempMat, mat2);
                                concatenatedFiles.add(tempFile2);
                            } catch (Exception exception) {
                                log.error(exception.getMessage());
                            }
                        }
                    }
                }
            }

            // 如果文件数量为奇数，将最后一个文件添加到新的列表中
            if (images.size() % 2 != 0) {
                Mat mat1 = images.get(images.size() - 2);
                Mat mat2 = images.get(images.size() - 1);
                Mat mat;
                try {
                    mat = ImageStitchingUtils.concatenateTwoImages(mat1, mat2);
                    concatenatedFiles.add(mat);
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }

            // 将新的列表作为下一轮的文件列表
            if (concatenatedFiles.size() > 0) {
                images = concatenatedFiles;
            } else {
                result.addAll(images);
                return result;
            }
        }
        result.addAll(images);
        return result;
    }

    private <T> List<List<T>> splitList(List<T> originalList) {
        int originalSize = originalList.size();
        // ceil为上舍入（同向下取整），结果会是平均分组，每组最大不超过40个
        // floor为下舍入（同向上取整）， 结果会是平均分组，每组最大不超过80个
        int groups = (int) Math.ceil(originalSize / 40f);
        System.out.println("组数：" + groups);
        // ceil向下取整，防止遗漏，也防止最后一组数量过少
        int sizeOfGroups = (int) Math.ceil((double) originalSize / groups);
        System.out.println("每组个数：" + sizeOfGroups);

        List<List<T>> resultList = new ArrayList<>();

        for (int i = 0; i < originalList.size(); i += sizeOfGroups) {
            int end = Math.min(i + sizeOfGroups, originalList.size());
            List<T> sublist = originalList.subList(i, end);
            resultList.add(new ArrayList<>(sublist));
        }

        return resultList;
    }

}
